﻿using Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Service
{
    public class TaskManager
    {
        private Stack<ICommand> executedCommands;
        public TaskManager()
        {
            executedCommands = new Stack<ICommand>();
        }

        private void Rollback()
        {
            while (executedCommands.Count > 0)
            {
                var command = executedCommands.Pop();
                command.Undo();
            }
            ActivityMonitor.Log("Transaction rollback.");
        }

        public bool AuthenticateUser(Model.Account account)
        {
            try
            {
                var command = new AuthenticateUser(account);
                if (command.Execute())
                    Model.CurrentSession.currentAccount = command.CurrentAccount;
                ActivityMonitor.Log("Authenticate user");
                return command.IsAuthentecated;
            }
            catch (Exception ex)
            {
                ReportSystemFailureManager.Report();
                throw;
            }
            return false;
        }

        public double CheckBalance(Model.Account account)
        {
            try
            {
                var command = new CheckBalance(account);
                command.Execute();
                ActivityMonitor.Log("Check Balance");
                return command.Balance;
            }
            catch (Exception ex)
            {
                Rollback();
                ReportSystemFailureManager.Report();
                throw;
            }

        }

        public String WithDrawMoney(Model.Account account, int amount)
        {
            Model.Account atm = new Model.Account();
            //fill atm details
            double atmBalance = 1000;
            double atmLimit = 500;
            //check atmbalance 
              if (CheckBalance(account) < 0)
            {
                ActivityMonitor.Log("Withdraw money: account not exists");
                return "No such account exists";
            }
            else if (atmBalance < amount)
            {
                ReportOutOfMoneyManager.Report();
                ActivityMonitor.Log("Withdraw money: out of money");
                return "ATM is out of money.";
            }
            else if (atmLimit < amount)
            {
                ActivityMonitor.Log("Withdraw money: out of limit");
                return "You can not withdraw more than $" + atmLimit + " per transaction.";
            }
            else if (CheckBalance(account) < amount)
            {
                ActivityMonitor.Log("Withdraw money: insufficient balance");
                return "You don't have sufficient balance";
            }
            else
            {
                try
                {
                    var command = new WithDrawAmount(account, amount);
                    if (command.Execute())
                    {
                        ActivityMonitor.Log("With draw money");
                        executedCommands.Push(command);
                    }
                    else
                    {
                        Rollback();
                    }
                }
                catch (Exception ex)
                {
                    Rollback();
                    ReportSystemFailureManager.Report();
                    throw;
                }

            }
            return "Success";
        }

        public bool ChangePinCode(Model.Account account, int oldPin)
        {
            try
            {
                var command = new ChangePin(account, oldPin);
                if (command.Execute())
                {
                    ActivityMonitor.Log("Change pin");
                    executedCommands.Push(command);
                }
                else
                    Rollback();
            }
            catch (Exception ex)
            {
                ReportSystemFailureManager.Report();
                throw;
            }
            return true;
        }

        public bool DepositeMoney(Model.Account account, int amount)
        {
            try
            {
                var command = new DepositeThroughParser(account, amount);
                if (command.Execute())
                {
                    executedCommands.Push(command);
                    ActivityMonitor.Log("Deposite money from parser.");
                }
                else
                    Rollback();
            }
            catch (Exception ex)
            {
                Rollback();
                ReportSystemFailureManager.Report();
                throw;
            }
            return true;
        }

        public bool TrasferAmount(string accountnofrom, int pinfrom, string accountnoto, int pinto, double amount)
        {
            try
            {
                var command = new BalanceTransfer(accountnofrom, pinfrom, accountnoto, pinto, amount);                
                if (command.Execute())
                {
                    executedCommands.Push(command);
                    ActivityMonitor.Log("Balance transferred");
                }
                else
                    Rollback();
            }
            catch (Exception ex)
            {
                Rollback();
                ReportSystemFailureManager.Report();
                throw;
            }
            return true;
        }

        public bool SMSFacade(string message)
        {
            throw new NotImplementedException();
        }
    }
}